<template>
  <div class="container">
    <img
      src="https://www.2008php.com/2023_Website_appreciate/2023-05-31/20230531193157SNDXn.jpg"
      class="element1"
    />
    <canvas class="element2" />
  </div>
  <br />
</template>

<script setup lang="ts">
import { onMounted } from 'vue'
import { Rectangle } from '@/common/model/app/rectangle'
//图片宽度
const imageWidth: Ref<number> = ref(0)
//图片高度
const imageHeight: Ref<number> = ref(0)
//Canvas宽度
const canvasWidth: Ref<number> = ref(0)
//Canvas高度
const canvasHeight: Ref<number> = ref(0)
//缩放系数
const scale: Ref<number> = ref(0)

//声明事件
const emit = defineEmits(['drawFinish', 'selectRectangle'])

onMounted(() => {
  const img = document.querySelector('img')
  const cvs = document.querySelector('canvas')
  const ctx = cvs?.getContext('2d')

  //初始化函数
  function init() {
    //初始化图片
    const image = new Image()
    image.src = 'https://www.2008php.com/2023_Website_appreciate/2023-05-31/20230531193157SNDXn.jpg'
    imageWidth.value = image.width
    imageHeight.value = image.height

    //初始化Canvas宽高
    canvasWidth.value = 828
    canvasHeight.value = 466

    scale.value =
      imageWidth.value >= imageHeight.value
        ? canvasWidth.value / imageWidth.value
        : canvasHeight.value / imageHeight.value
    if (cvs) {
      //保证Canvas清晰度
      cvs.width = canvasWidth.value * devicePixelRatio
      cvs.height = canvasHeight.value * devicePixelRatio
      cvs.style.width = canvasWidth.value + 'px'
      cvs.style.height = canvasHeight.value + 'px'
    }
    if (img) {
      img.width = canvasWidth.value * devicePixelRatio
      img.height = canvasHeight.value * devicePixelRatio
      img.style.width = canvasWidth.value + 'px'
      img.style.height = canvasHeight.value + 'px'
    }
  }

  init()

  //矩形集合
  const shapes: Array<Rectangle> = []

  //鼠标点击事件
  if (cvs) {
    cvs.onmousedown = (e) => {
      //获取客户端边界
      const startX = e.offsetX
      const startY = e.offsetY
      const bouding = cvs.getBoundingClientRect()
      const rect: Rectangle | null = new Rectangle(
        '#FF3F4C',
        startX / scale.value,
        startY / scale.value,
        0,
        0,
        scale.value,
      )
      const shape = getShape(e.offsetX, e.offsetY)

      //选中矩形
      selectShape(shape)

      if (shape) {
        emit('selectRectangle', shape)
        const mouseX = e.offsetX
        const mouseY = e.offsetY
        const rectanglex = shape.x * shape.scale
        const rectangley = shape.y * shape.scale

        //鼠标移动事件
        window.onmousemove = (e) => {
          //移动模式
          const disX = e.clientX - bouding.left - mouseX
          const disY = e.clientY - bouding.top - mouseY

          shape.x = (rectanglex + disX) / shape.scale
          shape.y = (rectangley + disY) / shape.scale
        }
      } else {
        shapes.push(rect)
        //鼠标移动事件
        window.onmousemove = (e) => {
          if (rect != null) {
            rect.width = Number((Math.abs(startX - e.offsetX) / scale.value).toFixed(2))
            rect.height = Number((Math.abs(startY - e.offsetY) / scale.value).toFixed(2))
            if (startX > e.offsetX && startY > e.offsetY) {
              rect.x = e.offsetX / rect.scale
              rect.y = e.offsetY / rect.scale
            }
            if (startX > e.offsetX && startY < e.offsetY) {
              rect.x = e.offsetX / rect.scale
            }
            if (startX < e.offsetX && startY > e.offsetY) {
              rect.y = e.offsetY / rect.scale
            }
            if (startX < e.offsetX && startY < e.offsetY) {
            }
          }
        }
      }

      //鼠标抬起事件
      window.onmouseup = () => {
        if (rect != null) {
          //清理误点矩形
          const isClear = clearShapes(rect)
          if (!isClear && shape == null) {
            emit('drawFinish', shapes)
          }
        }
        window.onmousemove = null
        window.onmouseup = null
      }
    }
  }

  //是否边缘
  // function isOverEdge(x: number, y: number, rect: Rectangle) {
  //   const edgeSize = 50 // 边缘检测的大小
  //   if (
  //     x / rect.scale >= rect.x - edgeSize &&
  //     x / rect.scale <= rect.x + rect.width + edgeSize &&
  //     y / rect.scale <= rect.y + edgeSize &&
  //     y / rect.scale >= rect.y - edgeSize
  //   ) {
  //     console.log('top')
  //     return 'top'
  //   }
  //   if (
  //     x / rect.scale >= Math.abs(rect.x - rect.height - edgeSize) &&
  //     x / rect.scale <= Math.abs(rect.x + rect.height + rect.width + edgeSize) &&
  //     y / rect.scale <= Math.abs(rect.y + rect.height + edgeSize) &&
  //     y / rect.scale >= Math.abs(rect.y + rect.height - edgeSize)
  //   ) {
  //     console.log('bottom')
  //     return 'bottom'
  //   }
  //   return null
  // }

  //获取矩形
  function getShape(x: number, y: number) {
    for (let i = shapes.length - 1; i >= 0; i--) {
      if (
        x >= shapes[i].minX * shapes[i].scale &&
        x <= shapes[i].maxX * shapes[i].scale &&
        y >= shapes[i].minY * shapes[i].scale &&
        y <= shapes[i].maxY * shapes[i].scale
      ) {
        return shapes[i]
      }
    }
  }

  //选中矩形
  function selectShape(shape?: Rectangle) {
    for (const shapet of shapes) {
      if (shapet == shape) {
        shapet.setcolor(1)
      } else {
        shapet.setcolor(0)
      }
    }
  }

  //清理误触矩形
  function clearShapes(shape: Rectangle) {
    if (shape.width < 50 && shape.height < 50) {
      const shapeIndex = shapes.findIndex((x) => x == shape)
      if (shapeIndex != -1) {
        //清理误点矩形
        shapes.splice(shapeIndex, 1)
        return true
      }
    }
    return false
  }

  //绘制
  function draw() {
    //每针调用一次绘制方法
    requestAnimationFrame(draw)
    if (cvs) {
      //绘制矩形
      ctx?.clearRect(0, 0, cvs.width, cvs.height)
    }
    for (const shape of shapes) {
      if (ctx) {
        shape.draw(ctx)
      }
    }
  }

  draw()
})
</script>

<style scoped>
.container {
  position: relative; /* 容器需要是相对定位 */
}

.element1 {
  position: absolute; /* 绝对定位 */
  top: 0; /* 顶部对齐 */
  left: 0; /* 左侧对齐 */
  object-fit: cover;
}

.element2 {
  position: absolute; /* 绝对定位 */
  top: 50%; /* 顶部对齐容器的中点 */
  left: 0; /* 左侧对齐 */
}
</style>
